package main

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"
)

func RunCmdStyle1(){
	cmd := exec.Command("cmd")

	in := bytes.NewBuffer(nil)
	cmd.Stdin = in  //绑定输入

	var out bytes.Buffer
	cmd.Stdout = &out;  //绑定输出

	go func() {
		in.WriteString("ping 127.0.0.1\n whoami\n telnet\n")  //执行多条指令，使用\n换行符间隔
	}()
	fmt.Println("开始执行....")

	err := cmd.Start()
	fmt.Println("执行完毕....")

	if err != nil{
		log.Fatal(err)
	}

	log.Println(cmd.Args)
	err = cmd.Wait()
	if err != nil{
		log.Printf("Command finised with error:%v",err)
	}
	fmt.Println(out.String())
}


//阻塞方式  需要执行结果
func RunCmdStyle2()(string, error){
	// 主要用于执行shell命令，并且返回shell的标准输出
	// 适用于执行普通非阻塞shell命令，且需要shell标准输出的
	// 阻塞式的执行外部shell命令的函数,等待执行完毕并返回标准输出

	//函数返回一个*Cmd，用于使用给出的参数执行name指定的程序
	//cmd := exec.Command("/bin/bash", "-c", s)
	//cmds := exec.Command(cmd)
	cmds := exec.Command("C:\\Windows\\System32\\cmd.exe", "net", "user")
	//cmds := exec.Command("C:\\Windows\\System32\\cmd.exe net user")  //错误用法

	//读取io.Writer类型的cmd.Stdout，再通过bytes.Buffer(缓冲byte类型的缓冲器)将byte类型转化为string类型
	// (out.String():这是bytes类型提供的接口)
	var out bytes.Buffer
	cmds.Stdout = &out

	//Run执行c包含的命令，并阻塞直到完成。这里stdout被取出，cmd.Wait()无法正确获取stdin,stdout,stderr，则阻塞在那了

	err := cmds.Run()
	checkErr(err)

	res := out.String()
	fmt.Println(cmds.Args)
	fmt.Println(res)
	return res, err
}


//阻塞方式  需要执行结果
func RunCmdStyle3(commandName string, params []string) bool{
	//需要对shell标准输出的逐行实时进行处理的
	//函数返回一个*Cmd，用于使用给出的参数执行name指定的程序

	//cmd := exec.Command(commandName, params...)




	return false
}


//非阻塞方式   不需要执行结果
func exec_shell_no_result(command string){
	//通过shell调用自己的程序，并且程序是死循环，此时无法获取返回结果(否则程序会一直阻塞直至调用的 程序结束)


}



//在任务管理器中调用exe程序
func RunExeStyle1(){

}


// 后台方式调用exe程序
func RunExeStyle2(){

}



func main() {
	//RunCmdStyle1()
	//RunCmdStyle2()
	RunCmdStyle3()

	RunExeStyle1()
	RunExeStyle2()
}


func checkErr(err error){
	if err != nil{
		fmt.Println(err)
		panic(err)
	}
}